﻿// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//需要安装jsoncpp
#include <iostream>
#include "json/json.h"
#include <string>
#include <windows.h>
#include <tchar.h>  
#include "wintoastlib.h"
#include "resource.h" 

using namespace std;
using namespace WinToastLib;

#if defined(GNUC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored “-Wdeprecated-declarations”
#elif defined(_MSC_VER)
#pragma warning(disable : 4996)
#endif

#ifdef  UNICODE  
#define _tcscpy     wcscpy  
#else  
#define _tcscpy     strcpy  
#endif 
#define MAKEINTRESOURCEA(i) (LPSTR)((ULONG_PTR)((WORD)(i)))
#define MAKEINTRESOURCEW(i) (LPWSTR)((ULONG_PTR)((WORD)(i)))
#ifdef UNICODE
#define MAKEINTRESOURCE MAKEINTRESOURCEW
#else
#define MAKEINTRESOURCE MAKEINTRESOURCEA
#endif // !UNICODE

#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#define MYWM_NOTIFYICON WM_USER+1 
NOTIFYICONDATA m_tnid;

class CustomHandler : public IWinToastHandler {
public:
    void toastActivated() const {
        std::wcout << L"The user clicked in this toast" << std::endl;
        exit(0);
    }

    void toastActivated(int actionIndex) const {
        std::wcout << L"The user clicked on action #" << actionIndex << std::endl;
        exit(16 + actionIndex);
    }

    void toastDismissed(WinToastDismissalReason state) const {
        switch (state) {
        case UserCanceled:
            std::wcout << L"The user dismissed this toast" << std::endl;
            exit(1);
            break;
        case TimedOut:
            std::wcout << L"The toast has timed out" << std::endl;
            exit(2);
            break;
        case ApplicationHidden:
            std::wcout << L"The application hid the toast using ToastNotifier.hide()" << std::endl;
            exit(3);
            break;
        default:
            std::wcout << L"Toast not activated" << std::endl;
            exit(4);
            break;
        }
    }

    void toastFailed() const {
        std::wcout << L"Error showing current toast" << std::endl;
        exit(5);
    }
};
HWND GetConsoleHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
    HWND hwndFound;         // This is what is returned to the caller.
    char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated
                                        // WindowTitle.
    char pszOldWindowTitle[MY_BUFSIZE]; // Contains original
                                        // WindowTitle.

    // Fetch current window title.

    GetConsoleTitle((LPWSTR)pszOldWindowTitle, MY_BUFSIZE);

    // Format a "unique" NewWindowTitle.

    wsprintf((LPWSTR)pszNewWindowTitle, (LPCWSTR)"%d/%d",
        GetTickCount(),
        GetCurrentProcessId());

    // Change current window title.

    SetConsoleTitle((LPWSTR)pszNewWindowTitle);

    // Ensure window title has been updated.

    Sleep(40);

    // Look for NewWindowTitle.

    hwndFound = FindWindow(NULL, (LPWSTR)pszNewWindowTitle);

    // Restore original window title.

    SetConsoleTitle((LPWSTR)pszOldWindowTitle);

    return(hwndFound);
}
void addIcon() { 
    m_tnid.cbSize = sizeof(NOTIFYICONDATA);
    m_tnid.hWnd = GetConsoleHwnd();
    m_tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
    m_tnid.uCallbackMessage = MYWM_NOTIFYICON; 
    char* pszMultiByte =const_cast<char *>("jsoncpp");
    int iSize;
    wchar_t* pwszUnicode;
    iSize = MultiByteToWideChar(CP_ACP, 0, pszMultiByte, -1, NULL, 0);
    pwszUnicode = (wchar_t*)malloc(iSize * sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, pszMultiByte, -1, pwszUnicode, iSize);
    _tcscpy(m_tnid.szTip, pwszUnicode);
    HICON hIcon;
    hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON1));
    m_tnid.hIcon = hIcon;
    m_tnid.uID = 2;  
    ::Shell_NotifyIcon(NIM_ADD, &m_tnid); 
    if (hIcon)::DestroyIcon(hIcon);
}


int main()
{
    addIcon();
    std::vector<std::wstring> actions;
    INT64 expiration = 0;
    if (!WinToast::isCompatible()) {
        std::wcerr << L"系统不支持!" << std::endl;
        return 0;
    }
    WinToast::instance()->setAppName(L"RightClickPlus");
    const  auto aumi = WinToast::configureAUMI(L" mohabouje ", L" wintoast ", L" wintoastexample ", L" 20161006 ");
    WinToast::instance()->setAppUserModelId(aumi);
    if (!WinToast::instance()->initialize()) {
        std::wcout << L"错误，无法初始化库！" << std::endl;
        return 0;
    }
    CustomHandler* handler = new CustomHandler;
    WinToastTemplate Tip = WinToastTemplate(WinToastTemplate::ImageAndText02);
    Tip.setExpiration(expiration);
    
    HWND hWnd = NULL;
    OpenClipboard(hWnd);
    char* jsonString = nullptr;
    if (IsClipboardFormatAvailable(CF_TEXT))
    {
        HANDLE h = GetClipboardData(CF_TEXT);
        jsonString = (char*)GlobalLock(h);
        GlobalUnlock(h);
    }
    CloseClipboard(); 
    if (jsonString == nullptr || jsonString == NULL) {
        Shell_NotifyIcon(NIM_DELETE, &m_tnid);
        return 0;
    }
    Json::Reader reader;
    Json::Value  rootObj ;
    reader.parse(jsonString, rootObj);
    if (rootObj.empty()) {
        Shell_NotifyIcon(NIM_DELETE, &m_tnid);
        return 0;
    }
    bool enter = false;
    int enter_num = 0;
    while (*jsonString)
    {
        if (*jsonString == '\n') {
            enter_num++;
        }
        if (enter_num > 2) {
            enter = true;
        }
        jsonString++;
    }
    string echoJson;
    if (enter) { 
        Json::FastWriter fastWriter;
        echoJson = fastWriter.write(rootObj); 
    }else{
        Json::StyledWriter styleWriter;
        echoJson = styleWriter.write(rootObj);
    }
    if (rootObj.empty() || echoJson.empty() || echoJson.size() == 0) {
        Shell_NotifyIcon(NIM_DELETE, &m_tnid);
        return 0;
    }
    hWnd = NULL;
    OpenClipboard(hWnd);
    EmptyClipboard();
    HANDLE hHandle = GlobalAlloc(GMEM_FIXED, echoJson.size()+1);
    char* pData = (char*)GlobalLock(hHandle);
    strcpy(pData,  (echoJson.c_str()));
    SetClipboardData(CF_TEXT, hHandle);
    GlobalUnlock(hHandle);
    CloseClipboard();
     
    if (enter) {
        Tip.setTextField(L"剪贴板数据已转换为【单行】", WinToastTemplate::SecondLine);
    }
    else {
        Tip.setTextField(L"剪贴板数据已转换为【多行】", WinToastTemplate::SecondLine);
    }
    
    if (!WinToast::instance()->showToast(Tip, handler)) {
        std::wcout << L"Error: Could not launch your toast notification!" << std::endl;
        Shell_NotifyIcon(NIM_DELETE, &m_tnid);
        return 0;
    }
    Sleep(expiration ? (DWORD)expiration + 600 : 300);
    Shell_NotifyIcon(NIM_DELETE, &m_tnid);
    return 0;
}


// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
